package cate.game.pvp.eliterace.simulator;

import cate.game.framework.advanced.AdvancedByteAttributes;
import cate.game.framework.advanced.AdvancedLongAttributes;
import cate.game.pvp.eliterace.data.EliteRaceKV;
import cate.game.pvp.eliterace.handler.*;
import cate.game.pvp.eliterace.timer.EliteRaceTimerTask.Settings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

import static cate.game.event.eliterace.EliteRaceTimerEvent.EventType.*;
import static cate.game.pvp.eliterace.data.EliteRaceKV.OP_SKIP_SEASON;

@Slf4j
public class BothEliteRaceControlSimulator extends EliteRaceSimulator {

    public BothEliteRaceControlSimulator(Supplier<EliteRaceKV> kvSupplier,
                                         Supplier<EliteRaceRecordOperation> recordOperationSupplier,
                                         Supplier<EliteRacePsOperation> psOperationSupplier,
                                         Supplier<EliteRaceFightOperation> fightOperationSupplier,
                                         Supplier<EliteRaceRankRwdOperation> rankRwdOperationSupplier,
                                         Supplier<EliteRaceBetOperation> betOperationSupplier,
                                         Supplier<EliteRaceVideoOperation> videoOperationSupplier) {
        super(
                kvSupplier,
                recordOperationSupplier,
                psOperationSupplier,
                fightOperationSupplier,
                rankRwdOperationSupplier,
                betOperationSupplier,
                videoOperationSupplier
        );
    }

    @Override
    public boolean isMatch(Settings settings) {
        return settings.getEventType() == OPEN
                || settings.getEventType() == SWITCH
                || settings.getEventType() == RANK_SETTLE
                || settings.getEventType() == INVITATION
                || settings.getEventType() == SHOW
                || settings.getEventType() == REST;
    }

    @Override
    public boolean runWith(Settings settings) {
        switch (settings.getEventType()) {
            case OPEN:
                return runOpenWith(settings);
            case SWITCH:
                return runSwitchWith(settings);
            case RANK_SETTLE:
                return runRankSettleWith(settings);
            case INVITATION:
                return runInvitationWith(settings);
            case SHOW:
                return runShowWith(settings);
            case REST:
                return runRestWith(settings);
            default:
                return true;
        }
    }

    private boolean runRestWith(Settings settings) {
        AdvancedByteAttributes opAttributes = getOpAttributes();
        EliteRaceKV kv = getKV();
        AdvancedLongAttributes attributes = getAttributes();
        if (opAttributes.hasAttribute(OP_SKIP_SEASON)) {
            kv.setSpec(settings.getSpec());
            attributes.setAttribute(REST.getFlag());
            return true;
        }
        if (attributes.hasAttribute(REST.getFlag())) {
            return true;
        }
        kv.setSpec(settings.getSpec());
        attributes.setAttribute(REST.getFlag());
        return true;
    }

    private boolean runShowWith(Settings settings) {
        AdvancedByteAttributes opAttributes = getOpAttributes();
        EliteRaceKV kv = getKV();
        AdvancedLongAttributes attributes = getAttributes();
        if (opAttributes.hasAttribute(OP_SKIP_SEASON)) {
            kv.setSpec(settings.getSpec());
            attributes.setAttribute(SHOW.getFlag());
            return true;
        }

        if (attributes.hasAttribute(SHOW.getFlag())) {
            return true;
        }
        kv.setSpec(settings.getSpec());
        attributes.setAttribute(SHOW.getFlag());
        return true;
    }

    private boolean runSwitchWith(Settings settings) {
        AdvancedLongAttributes attributes = getAttributes();
        if (attributes.hasAttribute(SWITCH.getFlag())) {
            return true;
        }

        EliteRaceKV kv = getKV();
        kv.setSpec(settings.getSpec());
        kv.getTimerSettings().forEach(s -> {
            long nextTriggerTimeMs = (kv.getSeason() % 2 == 1)
                    ? s.getTriggerTimeMs() + kv.getCycleTimeMs()
                    : s.getTriggerTimeMs() + kv.getCycleTimeMs() + DateUtils.MILLIS_PER_DAY;
            s.getSpec().setSeason(settings.getSpec().getSeason() + 1);
            s.setTriggerTimeMs(nextTriggerTimeMs);
        });

        attributes.setAttribute(SWITCH.getFlag());
        return true;
    }

    private boolean runOpenWith(Settings settings) {
        AdvancedLongAttributes attributes = getAttributes();
        EliteRaceKV kv = getKV();

        if (attributes.hasAttribute(OPEN.getFlag())
                && settings.getSpec().getSeason() == kv.getSeason()) {
            kv.setOpenTime(settings.getTriggerTimeMs());
            kv.setClosedTime(settings.getTriggerTimeMs() + kv.getCycleTimeMs());
            return true;
        }

        AdvancedByteAttributes opAttributes = getOpAttributes();
        opAttributes.clear();
        attributes.clear();
        kv.setSpec(settings.getSpec());
        kv.getEventAttributes().clear();
        kv.setSeason(settings.getSpec().getSeason());
        kv.setDay(1);
        kv.setOpenTime(settings.getTriggerTimeMs());
        kv.setClosedTime(settings.getTriggerTimeMs() + kv.getCycleTimeMs());
        attributes.setAttribute(OPEN.getFlag());
        return true;
    }

    final AtomicInteger counter = new AtomicInteger(0);

    private boolean runRankSettleWith(Settings settings) {
        AdvancedLongAttributes attributes = getAttributes();
        if (attributes.hasAttribute(RANK_SETTLE.getFlag())) {
            return true;
        }
        log.info("尝试从积分赛获取前128名玩家, 当前从counter：{}开始", counter.get());
        if (counter.incrementAndGet() >= 60) {
            counter.set(0);
        }
        EliteRacePsOperation psOperation = getPsOperation();
        if (psOperation.initialize()) {
            EliteRaceKV kv = getKV();
            kv.setSpec(settings.getSpec());
            attributes.setAttribute(RANK_SETTLE.getFlag());
            return true;
        } else {
            if (System.currentTimeMillis() - settings.getTriggerTimeMs() > DateUtils.MILLIS_PER_MINUTE * 5) {
                AdvancedByteAttributes opAttributes = getOpAttributes();
                log.info("超过五分钟获取不到资格赛玩家阵容, 跳过本赛季 {}", getKV().getSeason());
                opAttributes.setAttribute(OP_SKIP_SEASON);
                attributes.setAttribute(RANK_SETTLE.getFlag());
                return true;
            }

            return false;
        }
    }

    private boolean runInvitationWith(Settings settings) {
        AdvancedByteAttributes opAttributes = getOpAttributes();
        EliteRaceKV kv = getKV();
        AdvancedLongAttributes attributes = getAttributes();
        if (opAttributes.hasAttribute(OP_SKIP_SEASON)) {
            kv.setSpec(settings.getSpec());
            attributes.setAttribute(INVITATION.getFlag());
            return true;
        }

        if (attributes.hasAttribute(INVITATION.getFlag())) {
            return true;
        }
        kv.setSpec(settings.getSpec());
        attributes.setAttribute(INVITATION.getFlag());
        return true;
    }

}
